using System;
using System.IO;
using System.Text;
using System.Drawing;
using System.Resources;
using System.Reflection;
using System.Collections;
using System.Drawing.Text;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing.Imaging;
using Microsoft.Win32;
using needle.UI.Controls.Flat.Utilities.Drawing;
using needle.UI.Controls.Flat.Windows.Forms.Collections;
using needle.UI.Controls.Flat.Windows.Forms.Helpers;

namespace needle.UI.Controls.Flat.Windows.Forms
{
    [DefaultProperty("Appearance")]
    [DefaultEvent("SelectionChanged")]
    [Designer(typeof(TabControlDesigner))]
	[ToolboxItem(true)]
    public class TabControl : PanelBase
    {
		#region Nested types

		public enum VisualAppearance
        {
            MultiDocument = 0,
            MultiForm = 1,
            MultiBox = 2
        }

        public enum HideTabsModes
        {
            ShowAlways,
            HideAlways,
            HideUsingLogic,
            HideWithoutMouse
        }

        protected enum ImageStrip
        {
            LeftEnabled = 0,
            LeftDisabled = 1,
            RightEnabled = 2,
            RightDisabled = 3,
            Close = 4,
            Error = 5
        }

        protected enum PositionIndex
        {
            BorderTop			= 0,
            BorderLeft			= 1,
            BorderBottom		= 2, 
            BorderRight			= 3,
            ImageGapTop			= 4,
            ImageGapLeft		= 5,
            ImageGapBottom		= 6,
            ImageGapRight		= 7,
            TextOffset			= 8,
            TextGapLeft			= 9,
            TabsBottomGap		= 10,
            ButtonOffset		= 11,
        }

        protected class MultiRect
        {
            protected Rectangle mrect;
            protected int mindex;

            public MultiRect(Rectangle rect, int index)
            {
                mrect = rect;
                mindex = index;
            }

            public int Index
            {
                get { return mindex; }
            }            
            
            public Rectangle Rect
            {
                get { return mrect; }
                set { mrect = value; }
            }
            
            public int X
            {
                get { return mrect.X; }
                set { mrect.X = value; }
            }

            public int Y
            {
                get { return mrect.Y; }
                set { mrect.Y = value; }
            }

            public int Width
            {
                get { return mrect.Width; }
                set { mrect.Width = value; }
            }

            public int Height
            {
                get { return mrect.Height; }
                set { mrect.Height = value; }
            }
        }

		public class TabPageEventArgs : EventArgs
		{
			private TabPage page = null;

			public TabPageEventArgs(TabPage page)
			{
				this.page = page;
			}

			public TabPage Page
			{
				get {return this.page;}
			}
		}

		#endregion
        
        protected static int[,] mposition = {   {3, 1, 1, 1, 1, 2, 1, 1, 2, 1, 3, 2},	
                                                {6, 2, 2, 3, 3, 1, 1, 0, 1, 1, 2, 0}	
                                            };

		//Style, Neo default
		private Color m_TabControlBackColorColor = Color.FromArgb(242, 242, 228);
		
		protected static int mplainBorder = 3;
        protected static int mplainBorderDouble = 6;
        protected static int mtabsAreaStartInset = 5;
        protected static int mtabsAreaEndInset = 5;
        protected static float malphaIde = 1.5F;
        protected static int mbuttonGap = 3;
        protected static int mbuttonWidth = 14;
        protected static int mbuttonHeight = 14;
        protected static int mimageButtonWidth = 12;
        protected static int mimageButtonHeight = 12;
        protected static int mmultiBoxAdjust = 2;
        protected readonly Rectangle mnullPosition = new Rectangle(-999, -999, 0, 0);

        protected static ImageList minternalImages;

        protected int mtextHeight;
        protected int mimageWidth;
        protected int mimageHeight;
        protected int mimageGapTopExtra;
        protected int mimageGapBottomExtra;
        protected Rectangle mpageRect;
        protected Rectangle mpageAreaRect;
        protected Rectangle mtabsAreaRect;

        protected int mctrlTopOffset;			
        protected int mctrlLeftOffset;			
        protected int mctrlRightOffset;			
        protected int mctrlBottomOffset;	    
        protected int mstyleIndex;				
        protected int mpageSelected;			
        protected int mstartPage;				
        protected int mhotTrackPage;			
        protected int mtopYPos;                 
        protected int mbottomYPos;              
        protected int mleaveTimeout;            
        protected bool mdragFromControl;        
        protected bool mmouseOver;              
        protected bool mmultiline;              
        protected bool mmultilineFullWidth;     
        protected bool mshrinkPagesToFit;		
        protected bool mchanged;				
        protected bool mpositionAtTop;			
        protected bool mshowClose;				
        protected bool mshowArrows;				
        protected bool minsetPlain;				
        protected bool minsetBorderPagesOnly;   
        protected bool mselectedTextOnly;	    
        protected bool mrightScroll;			
        protected bool mleftScroll;				
        protected bool mdimUnselected;			
        protected bool mboldSelected;			
        protected bool mhotTrack;				
        protected bool mhoverSelect;			
        protected bool mrecalculate;			
        protected bool mleftMouseDown;			
        protected bool mleftMouseDownDrag;		
        protected bool mignoreDownDrag;         
        protected bool mdefaultColor;			
        protected bool mdefaultFont;			
		protected bool mrecordFocus;			
        protected bool midePixelArea;           
        protected bool midePixelBorder;         
		protected bool mdragOverSelect;			
        protected Point mleftMouseDownPos;		
		protected Point mmouseDragOver;			
        protected Color mhotTextColor;			
        protected Color mtextColor;				
        protected Color mtextInactiveColor;	    
        protected Color mbackIde;				
        protected Color mbuttonActiveColor;		
        protected Color mbuttonInactiveColor;	
        protected Color mbackLight;				
        protected Color mbackLightLight;		
        protected Color mbackDark;				
        protected Color mbackDarkDark;			
        protected HideTabsModes mhideTabsMode;  
        protected Timer moverTimer;             
		protected Timer mdragTimer;             
		protected VisualAppearance mappearance;	
        protected ImageList mimageList;			
        protected ArrayList mtabRects;			
        protected TabPageCollection mtabPages;	

        protected ImageButton mcloseButton;
        protected ImageButton mleftArrow;
        protected ImageButton mrightArrow;

        public delegate void DoubleClickTabEventHandler(object sender, TabPageEventArgs e);

        public event EventHandler ClosePressed;
        public event EventHandler SelectionChanging;
        public event EventHandler SelectionChanged;
        public event EventHandler PageGotFocus;
        public event EventHandler PageLostFocus;
        public event CancelEventHandler PopupMenuDisplay;
        public event MouseEventHandler PageDragStart;
        public event MouseEventHandler PageDragMove;
        public event MouseEventHandler PageDragEnd;
        public event MouseEventHandler PageDragQuit;
        public event DoubleClickTabEventHandler DoubleClickTab;

		#region Constructors

		static TabControl()
        {
			minternalImages = DrawHelpers.LoadBitmapStrip(Type.GetType("needle.UI.Controls.Flat.Windows.Forms.TabControl"),
                                                            "needle.Controls.Flat.Windows.Forms.Resources.ImagesTabControl.bmp",
															new Size(mimageButtonWidth, mimageButtonHeight),
															new Point(0,0));
        }

        public TabControl()
        {
			SetStyle(ControlStyles.DoubleBuffer | 
				     ControlStyles.AllPaintingInWmPaint |
				     ControlStyles.UserPaint, true);

            mtabRects = new ArrayList();
            mtabPages = new TabPageCollection();

            mtabPages.Clearing += new CollectionClearEventHandler(OnClearingPages);
            mtabPages.Cleared += new CollectionClearEventHandler(OnClearedPages);
            mtabPages.Inserting += new needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventHandler(OnInsertingPage);
            mtabPages.Inserted += new needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventHandler(OnInsertedPage);
            mtabPages.Removing += new needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventHandler(OnRemovingPage);
            mtabPages.Removed += new needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventHandler(OnRemovedPage);

            mstartPage = -1;						
            mpageSelected = -1;						
            mhotTrackPage = -1;					
            mimageList = null;						
            minsetPlain = true;
            mmultiline = false;
            mmultilineFullWidth = false;
            mdragFromControl = true;
            mmouseOver = false;
            mleftScroll = false;
            mdefaultFont = true;
            mdefaultColor = true;
            mrightScroll = false;
            mhoverSelect = false;
            mleftMouseDown = false;
            mignoreDownDrag = true;
            mselectedTextOnly = false;
            mleftMouseDownDrag = false;
            minsetBorderPagesOnly = false;
			mdragOverSelect = true;
            mhideTabsMode = HideTabsModes.ShowAlways;
			mrecordFocus = true;
            mstyleIndex = 1;
            mleaveTimeout = 200;
            mctrlTopOffset = 0;
            mctrlLeftOffset = 0;
            mctrlRightOffset = 0;
            mctrlBottomOffset = 0;
            mbuttonActiveColor = Color.FromArgb(128, this.ForeColor);
            mbuttonInactiveColor = mbuttonActiveColor;
            mtextColor = TabControl.DefaultForeColor;	
            mtextInactiveColor = Color.FromArgb(128, mtextColor);
            mhotTextColor = SystemColors.ActiveCaption;

            mcloseButton = new ImageButton(minternalImages, (int)ImageStrip.Close);
            mleftArrow = new ImageButton(minternalImages, (int)ImageStrip.LeftEnabled, (int)ImageStrip.LeftDisabled);
            mrightArrow = new ImageButton(minternalImages, (int)ImageStrip.RightEnabled, (int)ImageStrip.RightDisabled);

            //mcloseButton.BorderWidth = mleftArrow.BorderWidth = mrightArrow.BorderWidth = 1;

            mcloseButton.Click += new EventHandler(OnCloseButton);
            mleftArrow.Click += new EventHandler(OnLeftArrow);
            mrightArrow.Click += new EventHandler(OnRightArrow);

            mleftArrow.Size = mrightArrow.Size = mcloseButton.Size = new Size(mbuttonWidth, mbuttonHeight);

            Controls.AddRange(new Control[]{mcloseButton, mleftArrow, mrightArrow});

            mimageWidth = 16;
            mimageHeight = 16;

            SetAppearance(VisualAppearance.MultiForm);
            
            moverTimer = new Timer();
            moverTimer.Interval = mleaveTimeout;
            moverTimer.Tick += new EventHandler(OnMouseTick);

			mdragTimer = new Timer();
			mdragTimer.Interval = 200;
			mdragTimer.Tick += new EventHandler(OnDragOverTick);

            Microsoft.Win32.SystemEvents.UserPreferenceChanged += 
                new UserPreferenceChangedEventHandler(OnPreferenceChanged);

            DefineFont(SystemInformation.MenuFont);
            DefineBackColor(SystemColors.Control);
            DefineButtonImages();
			ResetAllowDrop();
			ResetDragOverSelect();

            Recalculate();
        }

		#endregion

		#region Dispose

        protected override void Dispose( bool disposing )
        {
            if(disposing)
            {
                Microsoft.Win32.SystemEvents.UserPreferenceChanged -= 
                    new UserPreferenceChangedEventHandler(OnPreferenceChanged);
            }
            base.Dispose(disposing);
        }

		#endregion

		#region Virtuals

		protected override void OnStyleChanged(object sender, StyleEventArgs args)
		{
			base.OnStyleChanged(sender, args);

			if (args.PropertyName == "TabControlBackColor") {this.TabControlBackColor = (Color)args.PropertyValue;}

			this.Invalidate(true);
		}

		protected override void OnPlansOfColorsChanged(object sender, PlansOfColorsChangedEventArgs args)
		{
			base.OnPlansOfColorsChanged(sender, args);

			if (this.Style!=null)
			{
				this.TabControlBackColor = this.Style.TabControlBackColor;
			}

			this.Invalidate(true);
		}

		
		public virtual void MakePageVisible(TabPage page)
		{
			MakePageVisible(mtabPages.IndexOf(page));
		}

		public virtual void MakePageVisible(int index)
		{
			if (!mshrinkPagesToFit && !mmultiline)
			{
				if ((index >= 0) && (index < mtabPages.Count))
				{
					if (index < mstartPage)
					{
						mstartPage = index;

						mrecalculate = true;
						Invalidate();
					}
					else
					{
						int xmax = GetMaximumDrawPos();

						Rectangle rect = (Rectangle)mtabRects[index];

						if (rect.Right >= xmax)
						{
							int newStart = index;

							int spaceLeft = xmax - rect.Width - mtabsAreaRect.Left - mtabsAreaStartInset;

							do
							{
								if (newStart == 0)
									break;

								Rectangle rectStart = (Rectangle)mtabRects[newStart - 1];
		
								if (rectStart.Width > spaceLeft)
									break;

								newStart--;
								spaceLeft -= rectStart.Width;

							} while(true);

							mstartPage = newStart;

							mrecalculate = true;
							Invalidate();
						}
					}
				}
			}
		}

		protected virtual bool ControlWantDoubleClick(IntPtr hwnd, Point mousePos, Control check)
		{
			if (check.Visible)
			{
				if (check.Enabled && (hwnd == check.Handle))
				{
					if (check == mleftArrow)
						OnLeftArrow(null, EventArgs.Empty);
	
					if (check == mrightArrow)
						OnRightArrow(null, EventArgs.Empty);
					
					return true;
				}
				else
				{
					Rectangle checkRect = new Rectangle(check.Location.X,
						check.Location.Y,
						check.Width,
						check.Height);

					if (checkRect.Contains(mousePos))
						return true;
				}
			}

			return false;
		}

		protected virtual bool ControlMouseTest(IntPtr hwnd, Point mousePos, Control check)
		{
			if ((hwnd == check.Handle) && check.Visible && check.Enabled)
			{
				if (check.ClientRectangle.Contains(mousePos))
				{
					if (check == mleftArrow)
						OnLeftArrow(null, EventArgs.Empty);
	
					if (check == mrightArrow)
						OnRightArrow(null, EventArgs.Empty);

					return true;
				}
			}

			return false;
		}

		public virtual void OnPopupMenuDisplay(CancelEventArgs e)
		{
			if (PopupMenuDisplay != null)
				PopupMenuDisplay(this, e);
		}

		public virtual void OnSelectionChanging(EventArgs e)
		{
			if (SelectionChanging != null)
				SelectionChanging(this, e);
		}

		public virtual void OnSelectionChanged(EventArgs e)
		{
			if (SelectionChanged != null)
				SelectionChanged(this, e);
		}

		public virtual void OnClosePressed(EventArgs e)
		{
			if (ClosePressed != null)
				ClosePressed(this, e);
		}

		public virtual void OnPageGotFocus(EventArgs e)
		{
			if (PageGotFocus != null)
				PageGotFocus(this, e);
		}
		
		public virtual void OnPageLostFocus(EventArgs e)
		{
			if (PageLostFocus != null)
				PageLostFocus(this, e);
		}

		public virtual void OnPageDragStart(MouseEventArgs e)
		{
			if (PageDragStart != null)
				PageDragStart(this, e);
		}

		public virtual void OnPageDragMove(MouseEventArgs e)
		{
			if (PageDragMove != null)
				PageDragMove(this, e);
		}

		public virtual void OnPageDragEnd(MouseEventArgs e)
		{
			if (PageDragEnd != null)
				PageDragEnd(this, e);
		}

		public virtual void OnPageDragQuit(MouseEventArgs e)
		{
			if (PageDragQuit != null)
				PageDragQuit(this, e);
		}
        
		public virtual void OnDoubleClickTab(TabPageEventArgs e)
		{
			if (DoubleClickTab != null)
				DoubleClickTab(this, e);
		}

		protected virtual void OnCloseButton(object sender, EventArgs e)
		{
			OnClosePressed(EventArgs.Empty);
		}

		protected virtual void OnLeftArrow(object sender, EventArgs e)
		{
			mstartPage--;

			mrecalculate = true;
			Invalidate();
		}
	
		protected virtual void OnRightArrow(object sender, EventArgs e)
		{
			mstartPage++;

			mrecalculate = true;
			Invalidate();
		}

		protected virtual void DefineFont(Font newFont)
		{
			base.Font = newFont;
	
			mtextHeight = newFont.Height;

			if (mimageHeight >= mtextHeight)
			{
				mimageGapTopExtra = 0;
				mimageGapBottomExtra = 0;
			}
			else
			{
				int extraHeight = mtextHeight - mimageHeight;

				mimageGapTopExtra = extraHeight / 2;
				mimageGapBottomExtra = extraHeight - mimageGapTopExtra;
			}
		}

		protected virtual void DefineBackColor(Color newColor)
		{
			base.BackColor = newColor;

			mbackLight = ControlPaint.Light(newColor);
			mbackLightLight = ControlPaint.LightLight(newColor);
			mbackDark = ControlPaint.Dark(newColor);
			mbackDarkDark = ControlPaint.DarkDark(newColor);

			mbackIde = ColorUtilities.TabBackgroundFromBaseColor(newColor);
		}
		
		protected virtual void DefineButtonImages()
		{
			ImageAttributes ia = new ImageAttributes();

			ColorMap activeMap = new ColorMap();
			ColorMap inactiveMap = new ColorMap();

			activeMap.OldColor = Color.Black;
			activeMap.NewColor = mbuttonActiveColor;
			inactiveMap.OldColor = Color.White;
			inactiveMap.NewColor = mbuttonInactiveColor;

			ia.SetRemapTable(new ColorMap[]{activeMap, inactiveMap}, ColorAdjustType.Bitmap);

		}

		protected virtual void SetAppearance(VisualAppearance appearance)
		{
			switch(appearance)
			{
				case VisualAppearance.MultiForm:
				case VisualAppearance.MultiBox:
					mshrinkPagesToFit = true;					
					mpositionAtTop = false;						
					mshowClose = false;							
					mshowArrows = false;						
					mboldSelected = false;						
					midePixelArea = true;                       
					midePixelBorder = false;                    
					break;
				case VisualAppearance.MultiDocument:
					mshrinkPagesToFit = false;					
					mpositionAtTop = true;						
					mshowClose = true;							
					mshowArrows = true;						    
					mboldSelected = true;						
					midePixelArea = true;                       
					midePixelBorder = false;                     
					break;
			}

			mhotTrack = false;							
			mdimUnselected = true;						

			if (mtabPages.Count > 0)
				mstartPage = 0;
			else
				mstartPage = -1;

			mappearance = appearance;
		}

		protected virtual bool HideTabsCalculation()
		{
			bool hideTabs = false;
        
			switch(mhideTabsMode)
			{
				case HideTabsModes.ShowAlways:
					hideTabs = false;
					break;
				case HideTabsModes.HideAlways:
					hideTabs = true;
					break;
				case HideTabsModes.HideUsingLogic:
					hideTabs = (mtabPages.Count <= 1);                            
					break;
				case HideTabsModes.HideWithoutMouse:
					hideTabs = !mmouseOver;
					break;
			}
            
			return hideTabs;
		}
		
		protected virtual void Recalculate()
		{
			mrecalculate = false;

			int tabButtonHeight = mposition[mstyleIndex, (int)PositionIndex.ImageGapTop] + 
				mimageGapTopExtra +
				mimageHeight + 
				mimageGapBottomExtra + 
				mposition[mstyleIndex, (int)PositionIndex.ImageGapBottom] +
				mposition[mstyleIndex, (int)PositionIndex.BorderBottom]; 

			int tabsAreaHeight = mposition[mstyleIndex, (int)PositionIndex.BorderTop] + 
				tabButtonHeight + mposition[mstyleIndex, (int)PositionIndex.TabsBottomGap];

			bool hideTabsArea = HideTabsCalculation();

			if (hideTabsArea)
			{
				mpageAreaRect = new Rectangle(0, 0, this.Width, this.Height);
				mtabsAreaRect = new Rectangle(0, 0, 0, 0);
			}
			else
			{
				if (mpositionAtTop)
				{
					mpageAreaRect = new Rectangle(0, tabsAreaHeight, this.Width, this.Height - tabsAreaHeight);

					mtabsAreaRect = new Rectangle(0, 0, this.Width, tabsAreaHeight);
				}
				else
				{
					mtabsAreaRect = new Rectangle(0, this.Height - tabsAreaHeight, this.Width, tabsAreaHeight);

					mpageAreaRect = new Rectangle(0, 0, this.Width, this.Height - tabsAreaHeight);
				}
			}

			int xendPos = 0;

			if (!hideTabsArea && mtabPages.Count > 0)
			{
				Rectangle tabPosition;
				
				if (mpositionAtTop)
					tabPosition = new Rectangle(0,		
						mtabsAreaRect.Bottom - tabButtonHeight - 
						mposition[mstyleIndex, (int)PositionIndex.BorderTop],
						mposition[mstyleIndex, (int)PositionIndex.BorderLeft] + 
						mposition[mstyleIndex, (int)PositionIndex.BorderRight],
						tabButtonHeight);
				else
					tabPosition = new Rectangle(0,		
						mtabsAreaRect.Top + 
						mposition[mstyleIndex, (int)PositionIndex.BorderTop],
						mposition[mstyleIndex, (int)PositionIndex.BorderLeft] + 
						mposition[mstyleIndex, (int)PositionIndex.BorderRight],
						tabButtonHeight);

				int xstartPos = mtabsAreaRect.Left + mtabsAreaStartInset;
				xendPos = GetMaximumDrawPos();

				int xwidth = xendPos - xstartPos;

				if (mmultiline)
					RecalculateMultilineTabs(xstartPos, xendPos, tabPosition, tabButtonHeight);
				else
					RecalculateSinglelineTabs(xwidth, xstartPos, tabPosition);
			}

			mpageRect = mpageAreaRect;

			int leftOffset = mctrlLeftOffset;
			int rightOffset = mctrlRightOffset;
			int topOffset = mctrlTopOffset;
			int bottomOffset = mctrlBottomOffset;

			if (midePixelBorder) 
			{
				leftOffset += 2;
				rightOffset += 2;

				if (mpositionAtTop || hideTabsArea)
					bottomOffset += 2;
                    
				if (!mpositionAtTop || hideTabsArea)
					topOffset += 2;
			}
        
			Point pageLoc = new Point(mpageRect.Left + leftOffset,
				mpageRect.Top + topOffset);

			Size pageSize = new Size(mpageRect.Width - leftOffset - rightOffset,
				mpageRect.Height - topOffset - bottomOffset);

			foreach(TabPage page in mtabPages)
			{
				if (page.Control != null)
				{
					page.Control.Size = pageSize;
					page.Control.Location = pageLoc;
				}
				else
				{
					page.Size = pageSize;
					page.Location = pageLoc;
				}
			}
            
			if (mtabPages.Count > 0)
			{
				Rectangle rect = (Rectangle)mtabRects[mtabPages.Count - 1];
				
				mrightScroll = (rect.Right > xendPos);
			}
			else
			{
				mrightScroll = false;
			}

			mleftScroll = (mstartPage > 0);

			RecalculateButtons();
		}

		protected virtual void RecalculateMultilineTabs(int xstartPos, int xendPos, 
			Rectangle tabPosition, int tabButtonHeight)
		{
			using (Graphics g = this.CreateGraphics())
			{
				if (mappearance == VisualAppearance.MultiBox)
					xendPos-=2;
                        
				int lineCount = 0;
                            
				mtopYPos = tabPosition.Y;
                            
				int xPos = xstartPos;
				int yPos = tabPosition.Y;
                            
				int fullLines = 0;
                            
				int lineIncrement = tabButtonHeight + 1;

				int selectedLine = 0;

				int yAdjust = 0;
                        
				ArrayList lineList = new ArrayList();
                            
				lineList.Add(new ArrayList());
                        
				for(int i=0; i<mtabPages.Count; i++)
				{
					TabPage page = mtabPages[i];
                            
					int tabWidth = GetTabPageSpace(g, page);
                                
					if (lineCount > 0)
					{
						if ((xPos + tabWidth) > xendPos)
						{
							xPos = xstartPos;
							yPos += lineIncrement;
                                        
							mbottomYPos = tabPosition.Y;

							mtabsAreaRect.Height += lineIncrement;
                                        
							mpageAreaRect.Height -= lineIncrement;
                                        
							if (mpositionAtTop)
								mpageAreaRect.Y += lineIncrement;
							else
							{
								yAdjust -= lineIncrement;
								mtabsAreaRect.Y -= lineIncrement;
							}
                                        
							lineList.Add(new ArrayList());
                                        
							fullLines++;
						}
					}

					if (tabWidth > (xendPos - xstartPos))
						tabWidth = xendPos - xstartPos;
                                
					Rectangle tabRect = new Rectangle(xPos, yPos, tabWidth, tabButtonHeight);
                                
					ArrayList thisLine = lineList[lineList.Count - 1] as ArrayList;
                                
					MultiRect tabEntry = new MultiRect(tabRect, i);
                                
					thisLine.Add(tabEntry);
                                
					if (i == mpageSelected)
						selectedLine = fullLines;
                                
					xPos += tabWidth + 1;
                                
					lineCount++;
				}

				int line = 0;

				if (mmultilineFullWidth)
					fullLines++;
                            
				foreach(ArrayList lineArray in lineList)
				{
					if (line < fullLines)
					{
						int numLines = lineArray.Count;
                                
						MultiRect itemEntry = (MultiRect)lineArray[numLines - 1];

						if (itemEntry.Rect.Right < (xendPos - 1))
						{
							int extra = (int)((xendPos - itemEntry.Rect.Right - 1) / numLines);
                                        
							int totalMove = 0;
                                        
							for(int i=0; i<numLines; i++)
							{
								MultiRect expandEntry = (MultiRect)lineArray[i];
                                        
								expandEntry.X += totalMove;
                                            
								expandEntry.Width += (int)extra;

								totalMove += extra;
							}
                                        
							itemEntry.Width += (xendPos - itemEntry.Rect.Right - 1);
						}
					}
                                
					line++;
				}

				if (mpositionAtTop)
				{
					if (selectedLine != (lineList.Count - 1))
					{
						ArrayList lastLine = (ArrayList)(lineList[lineList.Count - 1]);
                                    
						int lastOffset = ((MultiRect)lastLine[0]).Rect.Y;
                                
						for(int lineIndex=selectedLine+1; lineIndex<lineList.Count; lineIndex++)
						{
							ArrayList al = (ArrayList)lineList[lineIndex];
                                    
							for(int item=0; item<al.Count; item++)
							{
								MultiRect itemEntry = (MultiRect)al[item];
								itemEntry.Y -= lineIncrement;
							}
						}
                                    
						ArrayList sl = (ArrayList)lineList[selectedLine];
                                    
						for(int item=0; item<sl.Count; item++)
						{
							MultiRect itemEntry = (MultiRect)sl[item];
							itemEntry.Y = lastOffset;
						}
					}
				}
				else
				{
					if (selectedLine != 0)
					{
						ArrayList topLine = (ArrayList)(lineList[0]);
                                    
						int topOffset = ((MultiRect)topLine[0]).Rect.Y;
                                
						for(int lineIndex=0; lineIndex<selectedLine; lineIndex++)
						{
							ArrayList al = (ArrayList)lineList[lineIndex];
                                    
							for(int item=0; item<al.Count; item++)
							{
								MultiRect itemEntry = (MultiRect)al[item];
								itemEntry.Y += lineIncrement;
							}
						}
                                    
						ArrayList sl = (ArrayList)lineList[selectedLine];
                                    
						for(int item=0; item<sl.Count; item++)
						{
							MultiRect itemEntry = (MultiRect)sl[item];
							itemEntry.Y = topOffset;
						}
					}
				}

				foreach(ArrayList al in lineList)
				{
					foreach(MultiRect multiEntry in al)
					{
						Rectangle newRect = multiEntry.Rect;
                                    
						newRect.Y += yAdjust;
                                    
						mtabRects[multiEntry.Index] = newRect;
					}
				}
			}
		}

		protected virtual void RecalculateSinglelineTabs(int xwidth, int xstartPos, Rectangle tabPosition)
		{
			using (Graphics g = this.CreateGraphics())
			{
				mtopYPos = tabPosition.Y;
				mbottomYPos = mtopYPos;
            
				for(int i=0; i<mtabPages.Count; i++)
				{
					if (i < mstartPage)
						mtabRects[i] = (object)mnullPosition;  
					else
						mtabRects[i]= (object)tabPosition;	 
				}

				xwidth -= mtabPages.Count * (tabPosition.Width + 1);

				if (xwidth > 0)
				{
					ArrayList listNew = new ArrayList();
					ArrayList listOld = new ArrayList();

					for(int i=mstartPage; i<mtabPages.Count; i++)
						listNew.Add(mtabPages[i]);
            		
					int xAllowance;
            		
					do 
					{
						listOld = listNew;
            	
						listNew = new ArrayList();

						if (mshrinkPagesToFit)
						{
							xAllowance = xwidth / mtabPages.Count;
						}
						else
						{
							xAllowance = 999;
						}

						foreach(TabPage page in listOld)
						{
							int index = mtabPages.IndexOf(page);

							Rectangle rectPos = (Rectangle)mtabRects[index];

							int xSpace = GetTabPageSpace(g, page) - rectPos.Width;

							if (xSpace > xAllowance)
							{
								xSpace = xAllowance;
								listNew.Add(page);
							}

							rectPos.Width += xSpace;

							mtabRects[index] = (object)rectPos;

							xwidth -= xSpace;
						}
					} while ((listNew.Count > 0) && (xAllowance > 0) && (xwidth > 0));
				}

				for(int i=mstartPage; i<mtabPages.Count; i++)
				{
					Rectangle rectPos = (Rectangle)mtabRects[i];

					rectPos.X = xstartPos;

					mtabRects[i] = (object)rectPos;
					xstartPos += rectPos.Width + 1;
				}
			}
		}

		protected virtual void RecalculateButtons()
		{
			int buttonTopGap = 0;
            
			if (mmultiline)
			{
				int tabButtonHeight = mposition[mstyleIndex, (int)PositionIndex.ImageGapTop] + 
					mimageGapTopExtra +
					mimageHeight + 
					mimageGapBottomExtra + 
					mposition[mstyleIndex, (int)PositionIndex.ImageGapBottom] +
					mposition[mstyleIndex, (int)PositionIndex.BorderBottom]; 
        
				int tabsAreaHeight = mposition[mstyleIndex, (int)PositionIndex.BorderTop] + 
					tabButtonHeight + mposition[mstyleIndex, (int)PositionIndex.TabsBottomGap];
                
				buttonTopGap = mposition[mstyleIndex, (int)PositionIndex.ButtonOffset]	+ 
					(tabsAreaHeight - mbuttonHeight) / 2;

				if (!mpositionAtTop)
					buttonTopGap = mtabsAreaRect.Height - buttonTopGap - mbuttonHeight;
			}
			else
			{
				buttonTopGap = mposition[mstyleIndex, (int)PositionIndex.ButtonOffset]	+ 
					(mtabsAreaRect.Height - mbuttonHeight) / 2;
			}
        
			int xStart = mtabsAreaRect.Right - mbuttonWidth - mbuttonGap;

			if (mshowClose)
			{
				mcloseButton.Location = new Point(xStart, mtabsAreaRect.Top + buttonTopGap);

				if (xStart < 1)
					mcloseButton.Hide();
				else
					mcloseButton.Show();

				xStart -= mbuttonWidth;
			}
			else
				mcloseButton.Hide();

			if (mshowArrows)
			{
				mrightArrow.Location = new Point(xStart, mtabsAreaRect.Top + buttonTopGap);

				if (xStart < 1)
					mrightArrow.Hide();
				else
					mrightArrow.Show();
                    
				xStart -= mbuttonWidth;

				mleftArrow.Location = new Point(xStart, mtabsAreaRect.Top + buttonTopGap);

				if (xStart < 1)
					mleftArrow.Hide();
				else
					mleftArrow.Show();
                    
				xStart -= mbuttonWidth;

				mleftArrow.Enabled = mleftScroll;
				mrightArrow.Enabled = mrightScroll;
			}
			else
			{
				mleftArrow.Hide();
				mrightArrow.Hide();
			}

			mcloseButton.BackColor = mleftArrow.BackColor = mrightArrow.BackColor = mbackIde;
		}

		protected virtual int GetMaximumDrawPos()
		{
			int xendPos = mtabsAreaRect.Right - mtabsAreaEndInset;

			if (mshowClose)
				xendPos -= mbuttonWidth + mbuttonGap;

			if (mshowArrows)
				xendPos -= mbuttonWidth * 2;
				
			return xendPos;
		}

		protected virtual int GetTabPageSpace(Graphics g, TabPage page)
		{
			int width = mposition[mstyleIndex, (int)PositionIndex.BorderLeft] + 
				mposition[mstyleIndex, (int)PositionIndex.BorderRight];

			if ((page.Icon != null) || (((mimageList != null) || (page.ImageList != null)) && (page.ImageIndex != -1)))
			{
				width += mposition[mstyleIndex, (int)PositionIndex.ImageGapLeft] +
					mimageWidth + 
					mposition[mstyleIndex, (int)PositionIndex.ImageGapRight];
			}

			if ((page.Title != null) && (page.Title.Length > 0))
			{
				if (!mselectedTextOnly || (mselectedTextOnly && (mpageSelected == mtabPages.IndexOf(page))))
				{
					Font drawFont = base.Font;

					if (mboldSelected && page.Selected)
						drawFont = new Font(drawFont, FontStyle.Bold);

					SizeF dimension = g.MeasureString(page.Title, drawFont);			

					width += mposition[mstyleIndex, (int)PositionIndex.TextGapLeft] +
						(int)dimension.Width + 1; 
				}						 
			}

			return width;
		}

		protected virtual Rectangle ClippingRectangle()
		{
			int xReduce = mtabsAreaRect.Width - GetMaximumDrawPos();

			return new Rectangle(mtabsAreaRect.Left, 
				mtabsAreaRect.Top,
				mtabsAreaRect.Width - xReduce,
				mtabsAreaRect.Height);
		}

		protected virtual void ClipDrawingTabs(Graphics g)
		{
			Rectangle clipRect = ClippingRectangle();

			g.Clip = new Region(clipRect);
		}

		protected virtual void DrawTab(TabPage page, Graphics g, bool highlightText)
		{
			Rectangle rectTab = (Rectangle)mtabRects[mtabPages.IndexOf(page)];

			DrawTabBorder(ref rectTab, page, g);

			int xdraw = rectTab.Left + mposition[mstyleIndex, (int)PositionIndex.BorderLeft];
			int xmax = rectTab.Right - mposition[mstyleIndex, (int)PositionIndex.BorderRight];

			DrawTabImage(rectTab, page, g, xmax, ref xdraw);            
			DrawTabText(rectTab, page, g, highlightText, xmax, xdraw);
		}

		protected virtual void DrawTabImage(Rectangle rectTab, 
			TabPage page, 
			Graphics g, 
			int xmax, 
			ref int xdraw)
		{
			Icon drawIcon = page.Icon;
			Image drawImage = null;
			
			if ((drawIcon == null) && (page.ImageIndex != -1))
			{
				try
				{
					ImageList imageList = page.ImageList;

					if (imageList == null)
						imageList = mimageList;   

					if (imageList != null)
					{
						drawImage = imageList.Images[page.ImageIndex];
					}
				}
				catch(Exception)
				{
					drawImage = minternalImages.Images[(int)ImageStrip.Error];
				}
			}

			if ((drawImage != null) || (drawIcon != null))
			{
				if ((xdraw + mposition[mstyleIndex, (int)PositionIndex.ImageGapLeft]) <= xmax)
				{
					xdraw += mposition[mstyleIndex, (int)PositionIndex.ImageGapLeft];

					int yDraw = rectTab.Top + 
						mposition[mstyleIndex, (int)PositionIndex.ImageGapTop] + 
						mimageGapTopExtra;

					if ((xdraw + mimageWidth) <= xmax)
					{
						if (drawImage != null)
							g.DrawImage(drawImage, new Rectangle(xdraw, yDraw, mimageWidth, mimageHeight));
						else
							g.DrawIcon(drawIcon, new Rectangle(xdraw, yDraw, mimageWidth, mimageHeight));

						xdraw += mimageWidth + mposition[mstyleIndex, (int)PositionIndex.ImageGapRight];
					}
					else
					{
						int xSpace = xmax - xdraw;

						if (xSpace > 0)
						{
							if (drawImage != null)
							{
								g.DrawImage(drawImage, 
									new Point[]{new Point(xdraw, yDraw), 
												   new Point(xdraw + xSpace, yDraw), 
												   new Point(xdraw, yDraw + mimageHeight)},
									new Rectangle(0, 0, xSpace, 
									mimageHeight),
									GraphicsUnit.Pixel);
							}
                            
							xdraw = xmax;
						}
					}
				}
			}
		}

		protected virtual void DrawTabText(Rectangle rectTab, 
			TabPage page, 
			Graphics g, 
			bool highlightText,
			int xmax, 
			int xdraw)
		{
			if (!mselectedTextOnly || (mselectedTextOnly && page.Selected))
			{
				if (xdraw < xmax)
				{
					Color drawColor;
					SolidBrush drawBrush;
					Font drawFont = base.Font;

					if (highlightText)
						drawColor = mhotTextColor;
					else
					{
						if (mdimUnselected && !page.Selected)
						{
							drawColor = mtextInactiveColor;
						}
						else
							drawColor = mtextColor;
					}


					if (mboldSelected && page.Selected)
						drawFont = new Font(drawFont, FontStyle.Bold);

					drawBrush = new SolidBrush(drawColor);

					StringFormat drawFormat = new StringFormat();
					drawFormat.FormatFlags = StringFormatFlags.NoClip | StringFormatFlags.NoWrap;
					drawFormat.Trimming = StringTrimming.EllipsisCharacter;
					drawFormat.Alignment = StringAlignment.Center;
					drawFormat.HotkeyPrefix = HotkeyPrefix.Show;

					int yStart = rectTab.Top + mposition[mstyleIndex, (int)PositionIndex.ImageGapTop];

					int yEnd = rectTab.Bottom - 
						mposition[mstyleIndex, (int)PositionIndex.ImageGapBottom] - 
						mposition[mstyleIndex, (int)PositionIndex.BorderBottom];

					yStart += mposition[mstyleIndex, (int)PositionIndex.TextOffset];

					xdraw += mposition[mstyleIndex, (int)PositionIndex.TextGapLeft];

					if (xdraw < xmax)
					{
						Rectangle drawRect = new Rectangle(xdraw, yStart, xmax - xdraw, yEnd - yStart);

						g.DrawString(page.Title, drawFont, drawBrush, drawRect, drawFormat);
					}
                        	
					drawBrush.Dispose();
				}
			}
		}

		protected virtual void DrawTabBorder(ref Rectangle rectTab, TabPage page, Graphics g)
		{
			if (mappearance == VisualAppearance.MultiBox)
			{
				rectTab.Y -= mmultiBoxAdjust;
				DrawMultiBoxBorder(page, g, rectTab);
			}
			else
			{
				DrawIdeTabBorder(page, g, rectTab);
			}
		}
		
		protected virtual void DrawMultiBoxBorder(TabPage page, Graphics g, Rectangle rectPage)
		{
			if (page.Selected)
			{
				using (SolidBrush lightlight = new SolidBrush(mbackLightLight))
					g.FillRectangle(lightlight, rectPage);

				using (Pen darkdark = new Pen(mbackDarkDark))
					g.DrawRectangle(darkdark, rectPage);
			}
			else
			{
				using (SolidBrush backBrush = new SolidBrush(this.BackColor))
					g.FillRectangle(backBrush, rectPage.X + 1, rectPage.Y, rectPage.Width - 1, rectPage.Height);
            
				int index = mtabPages.IndexOf(page);

				bool drawSeparator = (index == mtabPages.Count - 1) ||
					(index < (mtabPages.Count - 1)) && 
					(mtabPages[index+1].Selected != true);
                                         
				if (mmultiline && !drawSeparator)
				{
					drawSeparator = true;
                    
					if (index < (mtabPages.Count - 1))
					{
						if (mtabPages[index+1].Selected == true)
						{
							Rectangle thisRect = (Rectangle)mtabRects[index];
							Rectangle nextRect = (Rectangle)mtabRects[index+1];

							if (thisRect.Y == nextRect.Y)
								drawSeparator = false;
						}
					}
				}

				if (drawSeparator)
				{
					using(Pen lightlight = new Pen(mbackLightLight),
							  dark = new Pen(mbackDark))
					{
						g.DrawLine(dark, rectPage.Right, rectPage.Top + 2, rectPage.Right, 
							rectPage.Bottom - mposition[mstyleIndex, (int)PositionIndex.TabsBottomGap] - 1);
						g.DrawLine(lightlight, rectPage.Right+1, rectPage.Top + 2, rectPage.Right+1, 
							rectPage.Bottom - mposition[mstyleIndex, (int)PositionIndex.TabsBottomGap] - 1);
					}
				}
			}
		}

		protected virtual void DrawPlainTabBorder(TabPage page, Graphics g, Rectangle rectPage)
		{
			using(Pen light = new Pen(mbackLightLight),
					  dark = new Pen(mbackDark),
					  darkdark = new Pen(mbackDarkDark))
			{
				int yLeftOffset = 0;
				int yRightOffset = 0;

				using (SolidBrush backBrush = new SolidBrush(base.BackColor))
				{
					if (page.Selected)
					{
						int yBorder;
						
						if (mpositionAtTop)
							yBorder = rectPage.Top + (mposition[mstyleIndex, (int)PositionIndex.BorderTop] / 2);
						else
							yBorder = rectPage.Top - (mposition[mstyleIndex, (int)PositionIndex.BorderTop] / 2);

						Rectangle rectBorder = new Rectangle(rectPage.Left, yBorder, rectPage.Width - 1, rectPage.Height);

						g.FillRectangle(backBrush, rectBorder);

						yLeftOffset = -2;
						yRightOffset = -1;
					}
				}

				if (mpositionAtTop)
				{
					g.DrawLine(light, rectPage.Left, rectPage.Bottom, rectPage.Left, rectPage.Top + 2); 
					g.DrawLine(light, rectPage.Left + 1 , rectPage.Top + 1, rectPage.Left + 1, rectPage.Top + 2); 

					g.DrawLine(light, rectPage.Left + 2, rectPage.Top + 1, rectPage.Right - 2, rectPage.Top + 1); 

					g.DrawLine(darkdark, rectPage.Right, rectPage.Bottom - yRightOffset, rectPage.Right, rectPage.Top + 2); 
					g.DrawLine(dark, rectPage.Right - 1, rectPage.Bottom - yRightOffset, rectPage.Right - 1, rectPage.Top + 2); 
					g.DrawLine(dark, rectPage.Right - 2, rectPage.Top + 1, rectPage.Right - 2, rectPage.Top + 2); 
					g.DrawLine(darkdark, rectPage.Right - 2, rectPage.Top, rectPage.Right, rectPage.Top + 2);
				}
				else
				{
					g.DrawLine(light, rectPage.Left, rectPage.Top + yLeftOffset, rectPage.Left, rectPage.Bottom - 2); 
					g.DrawLine(dark, rectPage.Left + 1 , rectPage.Bottom - 1, rectPage.Left + 1, rectPage.Bottom - 2); 

					g.DrawLine(dark, rectPage.Left + 2, rectPage.Bottom - 1, rectPage.Right - 2, rectPage.Bottom - 1); 
					g.DrawLine(darkdark, rectPage.Left + 2, rectPage.Bottom, rectPage.Right - 2, rectPage.Bottom); 

					g.DrawLine(darkdark, rectPage.Right, rectPage.Top, rectPage.Right, rectPage.Bottom - 2); 
					g.DrawLine(dark, rectPage.Right - 1, rectPage.Top + yRightOffset, rectPage.Right - 1, rectPage.Bottom - 2); 
					g.DrawLine(dark, rectPage.Right - 2, rectPage.Bottom - 1, rectPage.Right - 2, rectPage.Bottom - 2); 
					g.DrawLine(darkdark, rectPage.Right - 2, rectPage.Bottom, rectPage.Right, rectPage.Bottom - 2);
				}
			}
		}

		protected virtual void DrawIdeTabBorder(TabPage page, Graphics g, Rectangle rectPage)
		{
			using(Pen lightlight = new Pen(mbackLightLight),
					  backColor = new Pen(base.BackColor),
					  dark = new Pen(mbackDark),
					  darkdark = new Pen(mbackDarkDark))
			{
				if (page.Selected)
				{
					using (SolidBrush pageAreaBrush = new SolidBrush(this.BackColor))
						g.FillRectangle(pageAreaBrush, rectPage);

					if (mpositionAtTop)
					{
						g.DrawLine(backColor, rectPage.Left, rectPage.Bottom, rectPage.Right - 1, rectPage.Bottom);

						g.DrawLine(darkdark, rectPage.Right, rectPage.Top, rectPage.Right, rectPage.Bottom); 
					}
					else
					{
						g.DrawLine(lightlight, rectPage.Left, rectPage.Top - 1 , rectPage.Left, rectPage.Bottom); 

						g.DrawLine(darkdark, rectPage.Left + 1, rectPage.Bottom, rectPage.Right, rectPage.Bottom); 

						g.DrawLine(darkdark, rectPage.Right, rectPage.Top - 1 , rectPage.Right, rectPage.Bottom); 

						g.DrawLine(backColor, rectPage.Left + 1, rectPage.Top - 1, rectPage.Right - 1, rectPage.Top - 1);
					}
				}
				else
				{
					using(SolidBrush tabsAreaBrush = new SolidBrush(mbackIde))
						g.FillRectangle(tabsAreaBrush, rectPage);

					int index = mtabPages.IndexOf(page);

					bool drawSeparator = (index == mtabPages.Count - 1) ||
						(index < (mtabPages.Count - 1)) && 
						(mtabPages[index+1].Selected != true);
                                         
					if (mmultiline && !drawSeparator)
					{
						drawSeparator = true;
                    
						if (index < (mtabPages.Count - 1))
						{
							if (mtabPages[index+1].Selected == true)
							{
								Rectangle thisRect = (Rectangle)mtabRects[index];
								Rectangle nextRect = (Rectangle)mtabRects[index+1];

								if (thisRect.Y == nextRect.Y)
									drawSeparator = false;
							}
						}
					}

					if (drawSeparator)
					{
						using(Pen linePen = new Pen(mtextInactiveColor))
							g.DrawLine(linePen, rectPage.Right, rectPage.Top + 2, rectPage.Right, 
								rectPage.Bottom - mposition[mstyleIndex, (int)PositionIndex.TabsBottomGap] - 1);
					}
				}
			}
		}

		protected virtual void OnClearingPages(object sender, EventArgs e)
		{
			if (mpageSelected != -1)
			{
				DeselectPage(mtabPages[mpageSelected]);

				mpageSelected = -1;
				mstartPage = -1;
			}

			foreach(TabPage page in mtabPages)
				RemoveTabPage(page);

			mtabRects.Clear();
		}

		protected virtual void OnClearedPages(object sender, EventArgs e)
		{
			Recalculate();
            
			OnSelectionChanging(EventArgs.Empty);

			OnSelectionChanged(EventArgs.Empty);
            
			Invalidate();
		}

		protected virtual void OnInsertingPage(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			if (mpageSelected != -1)
			{
				if (mpageSelected >= e.Index)
					mpageSelected++;  
			}
		}

		protected virtual void OnInsertedPage(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			bool selectPage = false;

			TabPage page = sender as TabPage;

			page.PropertyChanged += new TabPage.PropChangeEventHandler(OnPagePropertyChanged);

			AddTabPage(page);
			
			if ((mpageSelected == -1) || (page.Selected))
			{
				OnSelectionChanging(EventArgs.Empty);

				if (mpageSelected != -1)
					DeselectPage(mtabPages[mpageSelected]);

				mpageSelected = mtabPages.IndexOf(page);

				if (mstartPage == -1)
					mstartPage = 0;	 

				selectPage = true;
			}

			mtabRects.Add((object)new Rectangle());

			if (selectPage)
			{
				Recalculate();

				SelectPage(page);

				OnSelectionChanged(EventArgs.Empty);
			}

			Recalculate();
			Invalidate();
		}

		protected virtual void OnRemovingPage(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			TabPage page = sender as TabPage;

			page.PropertyChanged -= new TabPage.PropChangeEventHandler(OnPagePropertyChanged);

			RemoveTabPage(page);

			mchanged = false;

			if (mpageSelected == e.Index)
			{
				OnSelectionChanging(EventArgs.Empty);

				mchanged = true;
				DeselectPage(page);
			}
		}

		protected virtual void OnRemovedPage(object sender, needle.UI.Controls.Flat.Windows.Forms.Collections.CollectionChangeEventArgs e)
		{
			if (mstartPage >= e.Index)
			{
				mstartPage--;

				if (mstartPage == -1)
				{
					if (mtabPages.Count > 0)
						mstartPage = 0;
				}
			}

			if (mpageSelected >= e.Index)
			{
				mpageSelected--;

				if (mpageSelected == -1)
				{
					if (mtabPages.Count > 0)
						mpageSelected = 0;
				}

				if (mpageSelected != -1)
					SelectPage(mtabPages[mpageSelected]);  
			}

			if (mchanged)
			{
				mchanged = false;

				OnSelectionChanged(EventArgs.Empty);
			}

			mtabRects.RemoveAt(0);

			Recalculate();
			Invalidate();
		}
			
		protected virtual void AddTabPage(TabPage page)
		{
			page.Shown = false;
        
			if (page.Control != null)
			{
				Form controlIsForm = page.Control as Form;

				page.Control.Hide();

				if (controlIsForm == null)
				{
					page.Control.GotFocus += new EventHandler(OnPageEnter);
					page.Control.LostFocus += new EventHandler(OnPageLeave);
					page.Control.MouseEnter += new EventHandler(OnPageMouseEnter);
					page.Control.MouseLeave += new EventHandler(OnPageMouseLeave);

					Controls.Add(page.Control);
				}
				else
				{
					controlIsForm.Activated += new EventHandler(OnPageEnter);
					controlIsForm.Deactivate += new EventHandler(OnPageLeave);
					controlIsForm.MouseEnter += new EventHandler(OnPageMouseEnter);
					controlIsForm.MouseLeave += new EventHandler(OnPageMouseLeave);
	
					controlIsForm.TopLevel = false;

					controlIsForm.Parent = this;

					controlIsForm.FormBorderStyle = FormBorderStyle.None;
				}

				if ((page.Control is Form) || (page.Control is Panel))
					page.Control.MouseDown += new MouseEventHandler(OnPageMouseDown);

				RecursiveMonitor(page.Control, true);
			}
			else
			{
				page.Hide();

				page.GotFocus += new EventHandler(OnPageEnter);
				page.LostFocus += new EventHandler(OnPageLeave);
				page.MouseEnter += new EventHandler(OnPageMouseEnter);
				page.MouseLeave += new EventHandler(OnPageMouseLeave);

				page.Dock = DockStyle.None;

				page.MouseDown += new MouseEventHandler(OnPageMouseDown);

				RecursiveMonitor(page, true);

				Controls.Add(page);
			}
		}

		protected virtual void RemoveTabPage(TabPage page)
		{
			if (page.Control != null)
				RemoveTabPageControl(page.Control);
			else
				RemoveTabPagePanel(page);
		}

		protected virtual void RemoveTabPageControl(Control c)
		{
			RecursiveMonitor(c, false);

			Form controlIsForm = c as Form;
			if ((c is Form) || (c is Panel))
				c.MouseDown -= new MouseEventHandler(OnPageMouseDown);

			if (controlIsForm == null)
			{
				c.GotFocus -= new EventHandler(OnPageEnter);
				c.LostFocus -= new EventHandler(OnPageLeave);
				c.MouseEnter -= new EventHandler(OnPageMouseEnter);
				c.MouseLeave -= new EventHandler(OnPageMouseLeave);
	
				ControlUtilities.Remove(this.Controls, c);
			}
			else
			{
				controlIsForm.Activated -= new EventHandler(OnPageEnter);
				controlIsForm.Deactivate -= new EventHandler(OnPageLeave);
				controlIsForm.MouseEnter -= new EventHandler(OnPageMouseEnter);
				controlIsForm.MouseLeave -= new EventHandler(OnPageMouseLeave);

				ControlUtilities.RemoveForm(this, controlIsForm);
			}
		}

		protected virtual void RemoveTabPagePanel(TabPage page)
		{
			RecursiveMonitor(page, false);

			page.MouseDown -= new MouseEventHandler(OnPageMouseDown);

			page.GotFocus -= new EventHandler(OnPageEnter);
			page.LostFocus -= new EventHandler(OnPageLeave);
			page.MouseEnter -= new EventHandler(OnPageMouseEnter);
			page.MouseLeave -= new EventHandler(OnPageMouseLeave);

			ControlUtilities.Remove(this.Controls, page);
		}

		protected virtual void OnPageMouseDown(object sender, MouseEventArgs e)
		{
			Control c = sender as Control;

			if (!c.ContainsFocus)
				c.Focus();
		}

		protected virtual void RecursiveMonitor(Control top, bool monitor)
		{
			foreach(Control c in top.Controls)
			{
				if (monitor)
				{
					c.GotFocus += new EventHandler(OnPageEnter);
					c.LostFocus += new EventHandler(OnPageLeave);
					c.MouseEnter += new EventHandler(OnPageMouseEnter);
					c.MouseLeave += new EventHandler(OnPageMouseLeave);
				}
				else
				{
					c.GotFocus -= new EventHandler(OnPageEnter);
					c.LostFocus -= new EventHandler(OnPageLeave);
					c.MouseEnter -= new EventHandler(OnPageMouseEnter);
					c.MouseLeave -= new EventHandler(OnPageMouseLeave);
				}
				
				RecursiveMonitor(c, monitor);
			}
		}

		protected virtual void OnPageEnter(object sender, EventArgs e)
		{
			OnPageGotFocus(e);
		}

		protected virtual void OnPageLeave(object sender, EventArgs e)
		{
			OnPageLostFocus(e);
		}
    
		protected virtual void OnPageMouseEnter(object sender, EventArgs e)
		{
			try
			{
				mmouseOver = true;
				moverTimer.Stop();
	            
				if (mhideTabsMode == HideTabsModes.HideWithoutMouse)
				{
					Recalculate();
					Invalidate();
				}
			}
			catch(Exception)
			{
			}
		}
	
		protected virtual void OnPageMouseLeave(object sender, EventArgs e)
		{
			try
			{
				moverTimer.Start();
			}
			catch(Exception)
			{
			}
		}

		protected virtual void OnMouseTick(object sender, EventArgs e)
		{
			try
			{
				mmouseOver = false;
				moverTimer.Stop();
	            
				if (mhideTabsMode == HideTabsModes.HideWithoutMouse)
				{
					Recalculate();
					Invalidate();
				}
			}
			catch(Exception)
			{
			}
		}

		protected virtual void OnDragOverTick(object sender, EventArgs e)
		{
			try
			{
				mdragTimer.Stop();

				if (mdragOverSelect)
				{
					TabPage mouseTab = TabPageFromPoint(mmouseDragOver);

					if (mouseTab != null)
					{
						if (!mouseTab.Selected)
							mouseTab.Selected = true;
					}
				}
			}
			catch(Exception)
			{
			}
		}
	
		protected virtual void OnPagePropertyChanged(object page, TabPage.PropChangeEventArgs e)
		{
			switch(e.PropertyName)
			{
				case "Control":
					Control pageControl = e.OldValue as Control;

					if (pageControl != null)
						RemoveTabPageControl(pageControl);
					else
						this.RemoveTabPagePanel(page as TabPage);

					this.AddTabPage(page as TabPage);

					if (mpageSelected != -1)
					{
						if (page == mtabPages[mpageSelected])
							this.SelectPage(page as TabPage);   
					}

					Recalculate();
					Invalidate();
					break;
				case "Title":
				case "ImageIndex":
				case "ImageList":
				case "Icon":
					mrecalculate = true;
					Invalidate();
					break;
				case "Selected":
					if (((TabPage)page).Selected)
					{
						MovePageSelection(page as TabPage);
						MakePageVisible(page as TabPage);
					}
					break;
			}
		}

		protected virtual Control FindFocus(Control root)
		{
			if (root.Focused)
				return root;

			foreach(Control c in root.Controls)
			{
				Control child = FindFocus(c);

				if (child != null)
					return child;
			}

			return null;
		}

		protected virtual void DeselectPage(TabPage page)
		{
			page.Selected = false;

			if (page.Control != null)
			{
				if (mrecordFocus)
				{
					if (page.Control.ContainsFocus)
						page.StartFocus = FindFocus(page.Control);
					else
						page.StartFocus = null;
				}

				page.Control.Hide();
			}
			else
			{
				if (mrecordFocus)
				{
					if (page.ContainsFocus)
						page.StartFocus = FindFocus(page);
					else
						page.StartFocus = null;
				}

				page.Hide();
			}
		}

		protected virtual void SelectPage(TabPage page)
		{
			page.Selected = true;

			if (page.Control != null)
				HandleShowingTabPage(page, page.Control);
			else
				HandleShowingTabPage(page, page);
		}

		protected virtual void HandleShowingTabPage(TabPage page, Control c)
		{
			if (!page.Shown)
			{
				Form f = c as Form;
                
				if ((f != null) && (f.AutoScale))
				{
					c.Show();
					c.Hide();
				}
                    
				page.Shown = true;
			}

			c.Show();

			if (page.StartFocus != null)
				page.StartFocus.Focus();
			else
				c.Focus();
		}
		
		protected virtual void MovePageSelection(TabPage page)
		{
			int pageIndex = mtabPages.IndexOf(page);

			if (pageIndex != mpageSelected)
			{
				OnSelectionChanging(EventArgs.Empty);

				if (mpageSelected != -1)
					DeselectPage(mtabPages[mpageSelected]);

				mpageSelected = pageIndex;

				if (mpageSelected != -1)
					SelectPage(mtabPages[mpageSelected]);

				if (mboldSelected || mselectedTextOnly || !mshrinkPagesToFit || mmultiline)
				{
					Recalculate();
					Invalidate();
				}

				OnSelectionChanged(EventArgs.Empty);

				Invalidate();
			}
		}

		protected bool ShouldSerializeContextPopupMenu()
		{
			return this.ContextMenu != null;
		}

		protected bool ShouldSerializePositionTop()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					return mpositionAtTop != false;
				case VisualAppearance.MultiDocument:
				default:
					return mpositionAtTop != true;
			}
		}

		protected bool ShouldSerializeShowClose()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					return mshowClose != false;
				case VisualAppearance.MultiDocument:
				default:
					return mshowClose != true;
			}
		}

		protected bool ShouldSerializeShowArrows()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					return mshowArrows != false;
				case VisualAppearance.MultiDocument:
				default:
					return mshowArrows != true;
			}
		}

		protected bool ShouldSerializeShrinkPagesToFit()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					return mshrinkPagesToFit != true;
				case VisualAppearance.MultiDocument:
				default:
					return mshrinkPagesToFit != false;
			}
		}

		protected bool ShouldSerializeBoldSelectedPage()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					return mboldSelected != false;
				case VisualAppearance.MultiDocument:
				default:
					return mboldSelected != true;
			}
		}
        
		protected bool ShouldSerializeIdePixelBorder()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					return midePixelBorder != false;
				case VisualAppearance.MultiDocument:
				default:
					return midePixelBorder != true;
			}
		}

		protected bool ShouldSerializeHideTabsMode()
		{
			return HideTabsMode != HideTabsModes.ShowAlways;
		}

		#endregion

		#region Overrides

		protected override bool ProcessMnemonic(char key)
		{
			int total = mtabPages.Count;
			int index = this.SelectedIndex + 1;
            
			for(int count=0; count<total; count++, index++)
			{
				if (index >= total)
					index = 0;

				TabPage page = mtabPages[index];
        
				int position = page.Title.IndexOf('&');

				if (IsMnemonic(key, page.Title))
				{
					this.SelectedTab = page;
                
					return true;
				}
			}
                        
			return false;
		}

		protected override void OnResize(EventArgs e)
		{
			Recalculate();
			Invalidate();
            
			base.OnResize(e);
		}

		protected override void OnSizeChanged(EventArgs e)
		{
			Recalculate();
			Invalidate();

			base.OnSizeChanged(e);
		}

		protected override void OnDoubleClick(EventArgs e)
		{
			Point pos = TabControl.MousePosition;

			int count = mtabRects.Count;

			for(int index=0; index<count; index++)
			{
				Rectangle local = (Rectangle)mtabRects[index];
				
				if (local != mnullPosition)
				{
					Rectangle screen = this.RectangleToScreen(local);

					if (screen.Contains(pos))
					{
						OnDoubleClickTab(new TabPageEventArgs(mtabPages[index]));
						break;
					}
				}
			}

			base.OnDoubleClick(e);
		}

		protected override void OnMouseUp(MouseEventArgs e)
		{
			if (mleftMouseDownDrag)
			{
				if (e.Button == MouseButtons.Left)
					OnPageDragEnd(e);
				else
					OnPageDragQuit(e);
                
				mleftMouseDownDrag = false;
				mignoreDownDrag = true;
			}

			if (e.Button == MouseButtons.Left)
			{
				mleftMouseDown = false;
			}
			else
			{
				if (e.Button == MouseButtons.Right)
				{
					Point mousePos = new Point(e.X, e.Y);
                
					if (mtabsAreaRect.Contains(mousePos))
					{
						CancelEventArgs ce = new CancelEventArgs();
                        
						OnPopupMenuDisplay(ce);
                        
						if (!ce.Cancel)
						{
							//if (mcontextMenu != null)
							//mcontextMenu.TrackPopup(this.PointToScreen(new Point(e.X, e.Y)));
						}
					}
				}
			}

			base.OnMouseUp(e);
		}

		protected override void OnMouseDown(MouseEventArgs e)
		{
			if (mleftMouseDownDrag)
			{
				OnPageDragQuit(e);
                
				mleftMouseDownDrag = false;
				mignoreDownDrag = true;
			}
			else
			{
				InternalMouseDown(new Point(e.X, e.Y));
			}

			base.OnMouseDown(e);
		}
        
		protected virtual void InternalMouseDown(Point mousePos)
		{
			int process = 0;

			for(int i=0; i<mtabPages.Count; i++)
			{
				Rectangle rect = (Rectangle)mtabRects[i];

				if (rect.Contains(mousePos))
				{
					if (mleftArrow.Visible)
					{
						if (mousePos.X >= mleftArrow.Left)
							return;
					}
					else
					{
						if (mcloseButton.Visible)
						{
							if (mousePos.X >= mcloseButton.Left)
								return;
						}
					}

					process = i;
					break;
				}
				else
				{
					if (rect.Right < mousePos.X)
						process = i;
				}
			}

			if (process < mtabPages.Count)
			{
				if (Control.MouseButtons == MouseButtons.Left)
				{
					mleftMouseDown = true;
					mignoreDownDrag = false;
					mleftMouseDownDrag = false;
					mleftMouseDownPos = mousePos;
				}
	                    
				MovePageSelection(mtabPages[process]);
				MakePageVisible(mtabPages[process]);

				if (mtabPages[process].Control != null)
					mtabPages[process].Control.Focus();
				else
					mtabPages[process].Focus();
			}
		}		

		protected override void OnMouseMove(MouseEventArgs e)
		{
			if (mleftMouseDown)
			{
				if (!mleftMouseDownDrag)
				{
					Point thisPosition = new Point(e.X, e.Y);
        
					bool startDrag = false;

					if (mdragFromControl)
						startDrag = !this.ClientRectangle.Contains(thisPosition);
					else
					{
						Rectangle dragRect = new Rectangle(mleftMouseDownPos, new Size(0,0));
                        
						dragRect.Inflate(SystemInformation.DoubleClickSize);
                        
						startDrag = !dragRect.Contains(thisPosition);
					}

					if (startDrag && !mignoreDownDrag)
					{
						OnPageDragStart(e);
		
						mleftMouseDownDrag = true;	
					}
				}
				else
				{
					OnPageDragMove(e);
				}
			}
			else
			{
				if (mhotTrack || mhoverSelect)
				{
					int mousePage = -1;
					bool pageChanged = false;

					Point mousePos = new Point(e.X, e.Y);

					for(int pos=0; pos<mtabPages.Count; pos++)
					{
						Rectangle rect = (Rectangle)mtabRects[pos];

						if (rect.Contains(mousePos))
						{
							mousePage = pos;
							break;
						}
					}

					if (mhoverSelect && !mmultiline && (mousePage != -1))
					{
						if (mousePage != mpageSelected)
						{
							MovePageSelection(mtabPages[mousePage]);

							pageChanged = true;
						}
					}

					if (mhotTrack && !pageChanged && (mousePage != mhotTrackPage))
					{
						Graphics g = this.CreateGraphics();

						ClipDrawingTabs(g);

						if (mhotTrackPage != -1)
							DrawTab(mtabPages[mhotTrackPage], g, false);

						mhotTrackPage = mousePage;

						if (mhotTrackPage != -1)
							DrawTab(mtabPages[mhotTrackPage], g, true);

						g.Dispose();
					}
				}
			}
            
			base.OnMouseMove(e);
		}

		protected override void OnMouseEnter(EventArgs e)
		{
			try
			{
				mmouseOver = true;
				moverTimer.Stop();
	            
				base.OnMouseEnter(e);
			}
			catch(Exception)
			{
			}
		}

		protected override void OnMouseLeave(EventArgs e)
		{
			if (mhotTrack)
			{
				int newTrackPage = -1;

				if (newTrackPage != mhotTrackPage)
				{
					Graphics g = this.CreateGraphics();

					ClipDrawingTabs(g);

					if (mhotTrackPage != -1)
						DrawTab(mtabPages[mhotTrackPage], g, false);

					mhotTrackPage = newTrackPage;

					g.Dispose();
				}
			}

			try
			{
				moverTimer.Start();
			}
			catch(Exception)
			{
			}

			base.OnMouseLeave(e);
		}		

		protected override void OnDragEnter(DragEventArgs e)
		{
			mmouseDragOver = new Point(-1, -1);
			base.OnDragEnter(e);
		}

		protected override void OnDragOver(DragEventArgs e)
		{
			if (mdragOverSelect)
			{
				Point mouseDragOver = PointToClient(new Point(e.X, e.Y));

				if (mouseDragOver != mmouseDragOver)
				{
					mmouseDragOver = mouseDragOver;

					mdragTimer.Stop();

					mdragTimer.Start();
				}
			}

			base.OnDragOver(e);
		}

		protected override void OnDragLeave(EventArgs e)
		{
			mdragTimer.Stop();

			base.OnDragLeave(e);
		}

		protected virtual void OnPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
		{
			if (mdefaultFont)
			{
				DefineFont(SystemInformation.MenuFont);

				Recalculate();
				Invalidate();
			}
		}

		protected override void OnSystemColorsChanged(EventArgs e)
		{
			if (mdefaultColor)
			{
				DefineBackColor(TabControl.DefaultBackColor);

				Recalculate();
				Invalidate();
			}

			base.OnSystemColorsChanged(e);
		}

		protected override void OnPaintBackground(PaintEventArgs e)
		{
		}

		protected override void OnPaint(PaintEventArgs e)
		{
			if (mrecalculate)
				Recalculate();

			using (SolidBrush pageAreaBrush = new SolidBrush(this.BackColor))
			{
				e.Graphics.FillRectangle(pageAreaBrush, mpageAreaRect);

				if (mappearance == VisualAppearance.MultiBox)
				{
					e.Graphics.FillRectangle(pageAreaBrush, mtabsAreaRect);
				}
				else
				{
					using(SolidBrush tabsAreaBrush = new SolidBrush(mbackIde))
						e.Graphics.FillRectangle(tabsAreaBrush, mtabsAreaRect);
				}
			}

			if (mappearance != VisualAppearance.MultiBox)
			{
				bool hiddenPages = HideTabsCalculation();

				using (Pen darkdark = new Pen(mbackDarkDark),
							dark = new Pen(mbackDark),
							lightlight = new Pen(mbackLightLight),
							backColor = new Pen(base.BackColor))
				{
					int borderGap = mposition[mstyleIndex, (int)PositionIndex.BorderTop];

					if (mpositionAtTop)
					{
						using(SolidBrush backBrush = new SolidBrush(base.BackColor))
							e.Graphics.FillRectangle(backBrush, 0, mtabsAreaRect.Bottom - borderGap, mtabsAreaRect.Width, borderGap);

						int indent = 0;

						if (midePixelBorder)
						{
							using(Pen llFore = new Pen(ControlPaint.LightLight(this.ForeColor)))
								e.Graphics.DrawRectangle(dark, 0, 0, this.Width - 1, this.Height - 1);
                                
							indent++;
						}
						else
						{
							if (midePixelArea)
							{
								e.Graphics.DrawLine(dark, 0, mtabsAreaRect.Top, mtabsAreaRect.Width, mtabsAreaRect.Top);
							}
						}
                        
						if (!hiddenPages)
							e.Graphics.DrawLine(lightlight, indent, 
								mtabsAreaRect.Bottom - borderGap, 
								mtabsAreaRect.Width - (indent * 2), 
								mtabsAreaRect.Bottom - borderGap);
					}
					else
					{
						using(SolidBrush backBrush = new SolidBrush(base.BackColor))
							e.Graphics.FillRectangle(backBrush, 0, mtabsAreaRect.Top, mtabsAreaRect.Width, borderGap);

						int indent = 0;

						if (midePixelBorder)
						{
							using(Pen llFore = new Pen(ControlPaint.LightLight(this.ForeColor)))
								e.Graphics.DrawRectangle(dark, 0, 0, this.Width - 1, this.Height - 1);
                                
							indent++;
						}
						else
						{
							if (midePixelArea)
							{
								e.Graphics.DrawLine(backColor, 0, mtabsAreaRect.Bottom - 1, mtabsAreaRect.Width, mtabsAreaRect.Bottom - 1);
							}
						}
                        
						if (!hiddenPages)
							e.Graphics.DrawLine(darkdark, indent, 
								mtabsAreaRect.Top + 2, 
								mtabsAreaRect.Width - (indent * 2), 
								mtabsAreaRect.Top + 2);
					}
				}
			}

			ClipDrawingTabs(e.Graphics);

			foreach(TabPage page in mtabPages)
				DrawTab(page, e.Graphics, false);
		}

		#endregion

		#region Internal helpers

		internal bool WantDoubleClick(IntPtr hwnd, Point mousePos)
		{
			return ControlWantDoubleClick(hwnd, mousePos, mleftArrow) ||
				ControlWantDoubleClick(hwnd, mousePos, mrightArrow) ||
				ControlWantDoubleClick(hwnd, mousePos, mcloseButton);
		}

		internal void ExternalMouseTest(IntPtr hwnd, Point mousePos)
		{
			if (!(ControlMouseTest(hwnd, mousePos, mleftArrow) ||
				ControlMouseTest(hwnd, mousePos, mrightArrow) ||
				ControlMouseTest(hwnd, mousePos, mcloseButton)))
				InternalMouseDown(mousePos);
		}

		#endregion

		#region Methods

		public void ResetHoverSelect()
		{
			HoverSelect = false;
		}

		public void ResetRecordFocus()
		{
			RecordFocus = true;
		}

		public TabPage TabPageFromPoint(Point mousePos)
		{
			for(int i=0; i<mtabPages.Count; i++)
			{
				Rectangle rect = (Rectangle)mtabRects[i];

				if (rect.Contains(mousePos))
				{
					if (mleftArrow.Visible)
					{
						if (mousePos.X >= mleftArrow.Left)
							return null;
					}
					else
					{
						if (mcloseButton.Visible)
						{
							if (mousePos.X >= mcloseButton.Left)
								return null;
						}
					}

					return mtabPages[i];
				}
			}

			return null;
		}

		public void ResetAllowDrop()
		{
			AllowDrop = true;
		}

		public void ResetButtonActiveColor()
		{
			ButtonActiveColor = Color.FromArgb(128, this.ForeColor);
		}

		public void ResetButtonInactiveColor()
		{
			ButtonInactiveColor = Color.FromArgb(128, this.ForeColor); 
		}

		public void ResetAppearance()
		{
			Appearance = VisualAppearance.MultiForm;
		}

		public void ResetContextPopupMenu()
		{
			this.ContextMenu = null;
		}

		public void ResetDragOverSelect()
		{
			DragOverSelect = true;
		}

		public void ResetHotTrack()
		{
			HotTrack = false;
		}

		public void ResetHotTextColor()
		{
			HotTextColor = SystemColors.ActiveCaption;
		}

		public void ResetTextColor()
		{   
			TextColor = TabControl.DefaultForeColor;
		}

        //public void TextTextInactiveColor()
        //{
        //    TextInactiveColor = Color.FromArgb(128, TabControl.DefaultForeColor);
        //}
		
		public void ResetImageList()
		{
			ImageList = null;
		}

		public void ResetIdePixelBorder()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					IdePixelBorder = false;
					break;
				case VisualAppearance.MultiDocument:
				default:
					IdePixelBorder = true;
					break;
			}
		}

		public void ResetIdePixelArea()
		{
			IdePixelArea = true;
		}

		public void ResetSelectedTextOnly()
		{
			SelectedTextOnly = false;
		}

		public void ResetMouseLeaveTimeout()
		{
			mleaveTimeout = 200;
		}

		public void ResetDragFromControl()
		{
			DragFromControl = true;
		}

		public void ResetHideTabsMode()
		{
			HideTabsMode = HideTabsModes.ShowAlways;
		}

		public void ResetPositionTop()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					PositionTop = false;
					break;
				case VisualAppearance.MultiDocument:
				default:
					PositionTop = true;
					break;
			}
		}

		public void ResetShowClose()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					ShowClose = false;
					break;
				case VisualAppearance.MultiDocument:
				default:
					ShowClose = true;
					break;
			}
		}

		public void ResetShowArrows()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					ShowArrows = false;
					break;
				case VisualAppearance.MultiDocument:
				default:
					ShowArrows = true;
					break;
			}
		}

		public void ResetShrinkPagesToFit()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					ShrinkPagesToFit = true;
					break;
				case VisualAppearance.MultiDocument:
				default:
					ShrinkPagesToFit = false;
					break;
			}
		}

		public void ResetBoldSelectedPage()
		{
			switch(mappearance)
			{
				case VisualAppearance.MultiBox:
				case VisualAppearance.MultiForm:
					BoldSelectedPage = false;
					break;
				case VisualAppearance.MultiDocument:
				default:
					BoldSelectedPage = true;
					break;
			}
		}

		public void ResetMultilineFullWidth()
		{
			MultilineFullWidth = false;
		}

		public void ResetMultiline()
		{
			Multiline = false;
		}

		public void ResetControlLeftOffset()
		{
			ControlLeftOffset = 0;
		}

		public void ResetControlTopOffset()
		{
			ControlTopOffset = 0;
		}

		public void ResetControlRightOffset()
		{
			ControlRightOffset = 0;
		}

		public void ResetControlBottomOffset()
		{
			ControlBottomOffset = 0;
		}

		public void ResetInsetPlain()
		{
			InsetPlain = true;
		}

		public void ResetInsetBorderPagesOnly()
		{
			InsetBorderPagesOnly = true;
		}

		#endregion

		#region Properties

		[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
		public new Control.ControlCollection Controls 
		{
			get { return base.Controls; }
		}

		[Category("Appearance")]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public virtual TabPageCollection TabPages
        {
            get { return mtabPages; }
        }

        [Category("Appearance")]
        public override Font Font
        {
            get { return base.Font; }

            set
            {
				if (value != null)
				{
					if (value != base.Font)
					{
						mdefaultFont = (value == SystemInformation.MenuFont);

						DefineFont(value);

						mrecalculate = true;
						Invalidate();
					}
				}
            }
        }

		[DefaultValue(true)]
		public override bool AllowDrop
		{
			get { return base.AllowDrop; }
			set { base.AllowDrop = value; }
		}

		[Category("Appearance")]
		public new Color ForeColor
		{
			get { return mtextColor; }
			
			set 
			{
				if (mtextColor != value)
				{
					mtextColor = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public new Color BackColor
		{
			get { return base.BackColor; }
			
			set 
			{
				if (this.BackColor != value)
				{
					mdefaultColor = (value == SystemColors.Control);

					DefineBackColor(value);
		
					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		private Color ButtonActiveColor
		{
			get { return mbuttonActiveColor; }

			set
			{
				if (mbuttonActiveColor != value)
				{
					mbuttonActiveColor = value;
					DefineButtonImages();
				}
			}
		}

		[Category("Appearance")]
		private Color ButtonInactiveColor
		{
			get { return mbuttonInactiveColor; }

			set
			{
				if (mbuttonInactiveColor != value)
				{
					mbuttonInactiveColor = value;
					DefineButtonImages();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(typeof(VisualAppearance), "MultiForm")]
		public virtual VisualAppearance Appearance
		{
			get { return mappearance; }
			
			set
			{
				if (mappearance != value)
				{
					SetAppearance(value);

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Behavour")]
		[DefaultValue(true)]
		public virtual bool DragOverSelect
		{
			get { return mdragOverSelect; }
			set { mdragOverSelect = value; }
		}

		[Category("Appearance")]
		[DefaultValue(false)]
		public virtual bool HotTrack
		{
			get { return mhotTrack; }
			
			set 
			{
				if (mhotTrack != value)
				{
					mhotTrack = value;

					if (!mhotTrack)
						mhotTrackPage = -1;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		private Color HotTextColor
		{
			get { return mhotTextColor; }
			
			set 
			{
				if (mhotTextColor != value)
				{
					mhotTextColor = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		private Color TextColor
		{
			get { return mtextColor; }
			
			set 
			{
				if (mtextColor != value)
				{
					mtextColor = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		private Color TextInactiveColor
		{
			get { return mtextInactiveColor; }
			
			set 
			{
				if (mtextInactiveColor != value)
				{
					mtextInactiveColor = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Browsable(false)]
		public virtual Rectangle TabsAreaRect
		{
			get { return mtabsAreaRect; }
		}

		[Category("Appearance")]
		public virtual ImageList ImageList
		{
			get { return mimageList; }

			set 
			{
				if (mimageList != value)
				{
					mimageList = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool PositionTop
		{
			get { return mpositionAtTop; }
			
			set
			{
				if (mpositionAtTop != value)
				{
					mpositionAtTop = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool ShowArrows
		{
			get { return mshowArrows; }
			
			set
			{
				if (mshowArrows != value)
				{
					mshowArrows = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool ShrinkPagesToFit
		{
			get { return mshrinkPagesToFit; }
			
			set 
			{
				if (mshrinkPagesToFit != value)
				{
					mshrinkPagesToFit = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool ShowClose
		{
			get { return mshowClose; }
			
			set
			{
				if (mshowClose != value)
				{
					mshowClose = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool BoldSelectedPage
		{
			get { return mboldSelected; }
			
			set 
			{
				if (mboldSelected != value)
				{
					mboldSelected = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(false)]
		public virtual bool MultilineFullWidth
		{
			get { return mmultilineFullWidth; }
            
			set
			{
				if (mmultilineFullWidth != value)
				{
					mmultilineFullWidth = value;
                    
					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(false)]
		public virtual bool Multiline
		{
			get { return mmultiline; }
			
			set 
			{
				if (mmultiline != value)
				{
					mmultiline = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(0)]
		public virtual int ControlLeftOffset
		{
			get { return mctrlLeftOffset; }
			
			set 
			{
				if (mctrlLeftOffset != value)
				{
					mctrlLeftOffset = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(0)]
		public virtual int ControlTopOffset
		{
			get { return mctrlTopOffset; }
			
			set 
			{
				if (mctrlTopOffset != value)
				{
					mctrlTopOffset = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(0)]
		public virtual int ControlRightOffset
		{
			get { return mctrlRightOffset; }
			
			set 
			{
				if (mctrlRightOffset != value)
				{
					mctrlRightOffset = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(0)]
		public virtual int ControlBottomOffset
		{
			get { return mctrlBottomOffset; }
			
			set 
			{
				if (mctrlBottomOffset != value)
				{
					mctrlBottomOffset = value;

					Recalculate();
					Invalidate();
				}
			}
		}
		
		[Category("Appearance")]
		[DefaultValue(true)]
		public virtual bool InsetPlain
		{
			get { return minsetPlain; }
			
			set 
			{
				if (minsetPlain != value)
				{
					minsetPlain = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(false)]
		public virtual bool InsetBorderPagesOnly
		{
			get { return minsetBorderPagesOnly; }
			
			set 
			{
				if (minsetBorderPagesOnly != value)
				{
					minsetBorderPagesOnly = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool IdePixelBorder
		{
			get { return midePixelBorder; }
			
			set 
			{
				if (midePixelBorder != value)
				{
					midePixelBorder = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		public virtual bool IdePixelArea
		{
			get { return midePixelArea; }
			
			set 
			{
				if (midePixelArea != value)
				{
					midePixelArea = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(false)]
		public virtual bool SelectedTextOnly
		{
			get { return mselectedTextOnly; }
			
			set 
			{
				if (mselectedTextOnly != value)
				{
					mselectedTextOnly = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Behavour")]
		[DefaultValue(200)]
		public int MouseLeaveTimeout
		{
			get { return mleaveTimeout; }
            
			set 
			{ 
				if (mleaveTimeout != value)
				{
					mleaveTimeout = value;
					moverTimer.Interval = value;
				}
			}
		}

		[Category("Behavour")]
		[DefaultValue(true)]
		public bool DragFromControl
		{
			get { return mdragFromControl; }
			set { mdragFromControl = value ; }
		}
        
		[Category("Appearance")]
		[DefaultValue(typeof(HideTabsModes), "ShowAlways")]
		public virtual HideTabsModes HideTabsMode
		{
			get { return mhideTabsMode; }
			
			set 
			{
				if (mhideTabsMode != value)
				{
					mhideTabsMode = value;

					Recalculate();
					Invalidate();
				}
			}
		}

		[Category("Appearance")]
		[DefaultValue(false)]
		public virtual bool HoverSelect
		{
			get { return mhoverSelect; }
			
			set 
			{
				if (mhoverSelect != value)
				{
					mhoverSelect = value;

					mrecalculate = true;
					Invalidate();
				}
			}
		}

		[Category("Behavour")]
		[DefaultValue(true)]
		public virtual bool RecordFocus
		{
			get { return mrecordFocus; }
			
			set 
			{
				if (mrecordFocus != value)
					mrecordFocus = value;
			}
		}

		[Browsable(false)]
		[DefaultValue(-1)]
		public virtual int SelectedIndex
		{
			get { return mpageSelected; }

			set
			{
				if ((value >= 0) && (value < mtabPages.Count))
				{
					if (mpageSelected != value)
					{
						OnSelectionChanging(EventArgs.Empty);

						if (mpageSelected != -1)
							DeselectPage(mtabPages[mpageSelected]);

						mpageSelected = value;

						if (mpageSelected != -1)
						{
							SelectPage(mtabPages[mpageSelected]);

							if (mpageSelected < mstartPage)
								mstartPage = mpageSelected;  
						}

						if (mboldSelected)
						{
							Recalculate();
							Invalidate();
						}

						OnSelectionChanged(EventArgs.Empty);

						Invalidate();
					}
				}
			}
		}

		[Browsable(false)]
		[DefaultValue(null)]
		public virtual TabPage SelectedTab
		{
			get 
			{
				if (mpageSelected == -1)
					return null;
				else
					return mtabPages[mpageSelected];
			}

			set
			{
				if (value != null)
				{
					int index = mtabPages.IndexOf(value);

					if (index != -1)
						this.SelectedIndex = index;
				}
			}
		}

		[Category("Style")]
		public Color TabControlBackColor
		{
			get{return m_TabControlBackColorColor;}
			set
			{
				m_TabControlBackColorColor = value;
				this.BackColor = m_TabControlBackColorColor;
			}
		}

		#endregion
    }
}
